#include "helper/sqlite/AbstractDB.h"

#include <system_error>
#include <filesystem>

#include <sqlite3.h>

#include "helper/sqlite/Statement.h"
#include "helper/sqlite/Error.h"

namespace helper {
namespace sqlite {

AbstractDB::AbstractDB(const std::string & url)
: IDB(url) // path as name of db
{
}
AbstractDB::~AbstractDB(){
}

std::error_code AbstractDB::destroy() {
  if(isOpened()){
    if(auto && ec = close(); ec) 
      return ec; 
  }
  return std::error_code();
}

std::error_code AbstractDB::_open() {
  std::error_code ec = error::sqlite_error(sqlite3_open_v2(url().c_str(),  (sqlite3 **)&_db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr));
  if(!ec){
    return ec;
  }
  error::ShowErrorMsg(__func__, __LINE__, ec);
  return ec;
}
std::error_code AbstractDB::_close() {
  std::error_code ec = error::sqlite_error(sqlite3_close_v2((sqlite3*)_db));
  if(!ec){
    return ec;
  }
  error::ShowErrorMsg(__func__, __LINE__, ec);
  return ec;
}



std::optional<Statement> AbstractDB::createStatement(const std::string & sql, std::error_code & ec) const{
  if(isOpened()){
    sqlite3_stmt * stmt = nullptr;
    ec = error::sqlite_error(sqlite3_prepare_v2((sqlite3*)_db, sql.c_str(), sql.length(), &stmt, nullptr));
    if(!ec){
      return std::make_optional<Statement>(this, stmt);
    }
    error::ShowErrorMsg(__func__, __LINE__, ec);
    return std::nullopt;
  }
  return std::nullopt;
}

void * AbstractDB::raw_handler() const {
  return isOpened() ? _db : nullptr;
}

bool isMemoryUrl(const std::string & url) {
  if(url.size() > 0 && url[0] == ':'){
    return true;
  }
  return false;
}

}//namespace sqlite
}//namespace helper



